<template>
    <div class="chess-container flex align-items-center justify-content-center row-reverse" v-loading="loading">
        <canvas ref="chessCanvas"></canvas>
        <cbl-chess-info :enemyUserInfo="enemyUserInfo" :userInfo="userInfo"
                        :matchTimesText="commonData.matchTimesText"
                        :userTimesText="commonData.userTimesText"></cbl-chess-info>
        <el-dropdown size="large" type="primary" class="operate">
            <span class="flex align-items-center">
                操作
            <el-icon :size="12" color="#fff" @click="handleRedirect">
                <ArrowUp/>
            </el-icon>
            </span>
            <template #dropdown>
                <el-dropdown-menu>
                    <el-dropdown-item @click="handleAdmitDefeat">认输</el-dropdown-item>
                    <el-dropdown-item @click="handleApplyDraw">申请和棋</el-dropdown-item>
                </el-dropdown-menu>
            </template>
        </el-dropdown>
        <cbl-message-box :info="messageBoxMatchInfo" @confirmClick="agreeDraw"
                         @cancelClick="disagreeDraw"></cbl-message-box>
    </div>
</template>

<script setup>
    import {ref, reactive, onMounted, getCurrentInstance, onBeforeUnmount, computed} from 'vue';
    import {ElMessage, ElMessageBox} from 'element-plus';
    import {useRouter} from 'vue-router';
    import {useStore} from 'vuex';
    import {DrawChess} from '@/class/index';
    import {api} from '@/utils/config';
    import service from '@/utils/service';
    import CblChessInfo from '@/components/CblChessInfo.vue';
    import CblMessageBox from '@/components/CblMessageBox.vue';
    import {ArrowUp} from '@element-plus/icons-vue';

    const chessCanvas = ref();
    const router = useRouter();
    const {proxy} = getCurrentInstance();
    const store = useStore();
    let drawChess = ref(null);
    const commonData = reactive({
        loading: false,
        timer: null,
        matchTimes: '',
        matchTimesText: '00:00',
        matchId: '',
        userTimesText: '00:00'
    });
    //弹框是否同意和棋
    const messageBoxMatchInfo = reactive({
        title: '比赛信息',
        content: `对方申请和棋，是否同意`,
        show: false,
        showCancelBtn: true,
        showConfirmBtn: true,
        cancelBtnText: '不同意',
        confirmBtnText: '同意'
    });
    const userInfo = computed(() => store.getters.getUserInfo);
    const enemyUserInfo = reactive({
        name: '',
        url: '',
        id: ''
    });

    const socket = {
        //平局
        draw() {
            ElMessageBox.alert('比赛时间结束，平局', '比赛结果', {
                type: 'info',
                confirmButtonText: 'OK',
                async callback() {
                    await router.back();
                }
            });
            if (commonData.timer) {
                window.clearTimeout(commonData.timer);
                commonData.timer = null;
            }
        },
        //监听棋子数据保存结果
        saveChessDataResult(data) {
            if (drawChess.value && data.code === 1) {
                if (data.isFinish) {
                    drawChess.value.clearTimer();
                    proxy.$socket.io.emit('getOwnUserInfo');
                    proxy.$socket.io.emit('getRankingList');
                } else {
                    drawChess.value.resetTimer();
                }
                drawChess.value.updateChessData(true);
            } else {
                drawChess.value.updateChessData(false);
                ElMessage({
                    showClose: false,
                    message: data.msg,
                    type: 'error',
                });
            }
        },
        //监听对方发过来的棋子数据
        acceptChessData(data) {
            console.log(data);
            drawChess.value.updateEnemyChess(data.chessData.list);
            if (data.isFinish) {
                drawChess.value.clearTimer();
                proxy.$socket.io.emit('getOwnUserInfo');
                proxy.$socket.io.emit('getRankingList');
                if (data.winnerId === userInfo.value.id) {
                    ElMessageBox.alert('恭喜你赢了', '比赛结果', {
                        type: 'success',
                        confirmButtonText: 'OK',
                        async callback() {
                            await router.back();
                        }
                    });
                } else {
                    ElMessageBox.alert('很遗憾你输了', '比赛结果', {
                        type: 'fail',
                        confirmButtonText: 'OK',
                        async callback() {
                            await router.back();
                        }
                    });
                }
            } else {
                drawChess.value.resetTimer();
            }
        },
        //收到对方主动认输的消息
        acceptAdmitDefeat() {
            proxy.$socket.io.emit('getOwnUserInfo');
            proxy.$socket.io.emit('getRankingList');
            if (commonData.timer) {
                window.clearTimeout(commonData.timer);
                commonData.timer = null;
            }
            drawChess.value.clearTimer();
            ElMessageBox.alert('对方主动认输，恭喜你赢了', '比赛结果', {
                type: 'success',
                confirmButtonText: 'OK',
                async callback() {
                    await router.back();
                }
            });
        },
        //主动认输后的保存结果
        async admitDefeatResult(data) {
            if (data.code === 1) {
                proxy.$socket.io.emit('getOwnUserInfo');
                proxy.$socket.io.emit('getRankingList');
                if (commonData.timer) {
                    window.clearTimeout(commonData.timer);
                    commonData.timer = null;
                }
                drawChess.value.clearTimer();
                await router.back();
            } else {
                ElMessageBox.alert(data.msg, '信息', {
                    type: 'fail',
                    confirmButtonText: 'OK'
                });
            }
        },
        //监听对方申请和棋
        applyDraw() {
            messageBoxMatchInfo.show = true;
        },
        //监听对方是否接受和棋
        acceptApplyDrawResult(data) {
            if (data.agree) {
                if (commonData.timer) {
                    window.clearTimeout(commonData.timer);
                    commonData.timer = null;
                }
                drawChess.value.clearTimer();
                ElMessageBox.alert('对方同意和棋', '申请结果', {
                    type: 'success',
                    confirmButtonText: 'OK',
                    async callback() {
                        await router.back();
                    }
                });
            } else {
                ElMessageBox.alert('对方拒绝和棋', '申请结果', {
                    type: 'fail',
                    confirmButtonText: 'OK',
                    async callback() {
                    }
                });
            }
        },
        //保存和棋结果
        async saveApplyDrawResult(data) {
            if (data.code === 1) {
                if (commonData.timer) {
                    window.clearTimeout(commonData.timer);
                    commonData.timer = null;
                }
                drawChess.value.clearTimer();
                await router.back();
            } else {
                ElMessageBox.alert(data.msg, '信息', {
                    type: 'fail',
                    confirmButtonText: 'OK'
                });
            }
        }
    };
    onMounted(async () => {
        proxy.$addSockets(socket, proxy);
        await store.dispatch('handleSetInChess', true);
        loadChess();
    });
    onBeforeUnmount(async () => {
        if (commonData.timer) {
            window.clearTimeout(commonData.timer);
            commonData.timer = null;
        }
        proxy.$removeSockets(socket, proxy);
        await store.dispatch('handleSetInChess', false);
    });
    //加载比赛数据
    const loadChess = () => {
        commonData.loading = true;
        service.doGet(api['chess'])
            .then(async (response) => {
                if (response.code === 1) {
                    const data = response.data.chess;
                    enemyUserInfo.name = data.enemyUserInfo['name'];
                    enemyUserInfo.url = data.enemyUserInfo['url'];
                    enemyUserInfo.id = data.enemyUserInfo['id'];
                    commonData.matchTimes = data.createdAt;
                    commonData.matchId = data.id;
                    dealTimer();
                    drawChess.value = new DrawChess({
                        canvas: chessCanvas.value,
                        width: 360,
                        height: 414,
                        camp: data.camp,
                        matchId: data.id,
                        enemy: data.enemy,
                        chessData: data.chessData,
                        proxy,
                        userInfo: userInfo.value,
                        getMatchTimes(times) {
                            commonData.userTimesText = getMatchTimesText(times);
                        }
                    });
                } else {
                    await router.back();
                }
                commonData.loading = false;
            }).catch(async (err) => {
            console.log(err);
            commonData.loading = false;
            await router.back();
        })
    };
    //处理比赛计时器
    const dealTimer = () => {
        commonData.timer = window.setTimeout(() => {
            let createdAtTime = new Date(commonData.matchTimes).getTime();
            let currentTime = Date.now();
            let matchTimes = Math.floor((currentTime - createdAtTime) / 1000);
            if (matchTimes > 20 * 60) {
                window.clearTimeout(commonData.timer);
                commonData.timer = null;
                ElMessageBox.alert('比赛时间结束，平局', '比赛结果', {
                    type: 'info',
                    confirmButtonText: 'OK',
                    async callback() {
                        await router.back();
                    }
                });
                proxy.$socket.io.emit('draw', {matchId: commonData.matchId, toUserId: enemyUserInfo.id});
            } else {
                commonData.matchTimesText = getMatchTimesText(20 * 60 - matchTimes);
                dealTimer();
            }
        }, 1000)
    };
    const getMatchTimesText = (matchTimes) => {
        const minutes = Math.floor(matchTimes / 60);
        const seconds = matchTimes % 60;
        return `${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + seconds : seconds}`;
    };
    //主动认输
    const handleAdmitDefeat = () => {
        proxy.$socket.io.emit('admitDefeat', {matchId: commonData.matchId, toUserId: enemyUserInfo.id});
    };
    //申请和棋
    const handleApplyDraw = () => {
        proxy.$socket.io.emit('applyDraw', {matchId: commonData.matchId, toUserId: enemyUserInfo.id});
    };
    //同意和棋
    const agreeDraw = () => {
        proxy.$socket.io.emit('applyDrawResult', {
            matchId: commonData.matchId,
            toUserId: enemyUserInfo.id,
            agree: true
        });
        messageBoxMatchInfo.show = false;
    };
    //不同意和棋
    const disagreeDraw = () => {
        proxy.$socket.io.emit('applyDrawResult', {
            matchId: commonData.matchId,
            toUserId: enemyUserInfo.id,
            agree: false
        });
        messageBoxMatchInfo.show = false;
    }
</script>

<style scoped lang="less">
    .chess-container {
        position: relative;
        height: 100%;
        background: url("../assets/chess-pan1.jpg") no-repeat center center;
        -webkit-background-size: cover;
        background-size: cover;

        .operate {
            position: absolute;
            left: 0;
            bottom: 0;
            border: none;
            --el-dropdown-menu-box-shadow: none;

            &:hover {
                border: none;
            }

            span {
                border: none;
                background: #9b8d80;
                padding: 5px 10px;
                font-size: 12px;
                color: #fff;
                cursor: pointer;

                &:hover {
                    border: none;
                }
            }
        }
    }
</style>